"""
简单的web服务端程序
"""
from socket import *
from select import select
import re


class WebServer:
    def __init__(self, host="", port=0, html=None):
        self.host = host
        self.port = port
        self.address = (host, port)
        self.html = html  # 网页位置
        self.rlist = []
        self.sock = self._create_socket()

    def _create_socket(self):
        sock = socket()
        sock.bind(self.address)
        sock.setblocking(False)
        return sock

    def _connect(self, sock):
        conn, addr = self.sock.accept()
        conn.setblocking(False)
        self.rlist.append(conn)  # 增加关注

    # 启动服务
    def start(self):
        self.sock.listen(5)
        print("Listen the port %d" % self.port)
        self.rlist.append(self.sock)  # 初始监听
        # 循环监控
        while True:
            rs, ws, xs = select(self.rlist, [], [])
            for r in rs:
                if r is self.sock:
                    self._connect(r)  # 连接客户端
                else:
                    try:
                        self._handle(r)
                    except:
                        pass
                    self.rlist.remove(r)
                    r.close()

    # 具体处理浏览器http请求
    def _handle(self, conn):
        # 接收HTTP请求
        request = conn.recv(1024).decode()
        try:
            # 解析出请求内容
            info = re.search(r"[A-Z]+\s+(/\S*)", request).group(1)
            print("请求内容:", info)
        except Exception:
            pass  # 客户端已退出
        else:
            # 组织响应
            self._response(conn, info)

    # 组织发送响应
    def _response(self, conn, info):
        # 确定需要的网页名称
        if info == "/":
            filename = self.html + "/index.html"
        else:
            filename = self.html + info

        # 组织发送响应
        try:
            file = open(filename, 'rb')
        except:
            status = "404 Not Found"
            with open(self.html + "/404.html", 'rb') as file:
                data = file.read()
            response = self._get_data(status, data)
        else:
            status = "200 OK"
            data = file.read()
            response = self._get_data(status, data)
        finally:
            conn.send(response)  # 发送响应

    def _get_data(self, status, data):
        response = "HTTP/1.1 %s\r\n" % status
        response += "Content-Type:text/html\r\n"
        response += "\r\n"
        response = response.encode() + data
        return response


if __name__ == '__main__':
    # 类的参数  host  port  网页
    httpd = WebServer(host="0.0.0.0", port=8000, html="./static")
    httpd.start()  # 启动服务
